<template>
  <div class="content-box-full menu-box">
    <container-box>
      <template #header>
        <el-button
          v-permission="'sys:menu:save'"
          style="margin-bottom: 10px"
          type="primary"
          :icon="Plus"
          @click="openMenuDialog('add')"
          >新增
        </el-button>
      </template>
      <template #default>
        <el-table
          :data="tableData"
          :empty-text="isLoadingTable ? '加载中...' : '暂无数据'"
          class="table-box"
          height="100%"
          stripe
          fit
          border
          row-key="menuId"
          default-expand-all
          highlight-current-row
        >
          <el-table-column
            align="center"
            header-align="center"
            type="index"
            label="序号"
            width="80"
          ></el-table-column>
          <el-table-column prop="name" header-align="center" align="left" width="150" label="名称">
          </el-table-column>
          <el-table-column
            prop="parentName"
            header-align="center"
            align="center"
            width="120"
            label="上级菜单"
          >
          </el-table-column>
          <el-table-column header-align="center" align="center" label="图标">
            <template v-slot="{ row }">
              <i class="iconfont" :class="`icon-${row.icon}`"></i>
            </template>
          </el-table-column>
          <el-table-column prop="type" header-align="center" align="center" label="$类型">
            <template v-slot="scope">
              <el-tag v-if="scope.row.type === 0" size="small">目录</el-tag>
              <el-tag v-else-if="scope.row.type === 1" size="small" type="success">菜单</el-tag>
              <el-tag v-else-if="scope.row.type === 2" size="small" type="info">按钮</el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="orderNum" header-align="center" align="center" label="排序号">
          </el-table-column>
          <el-table-column
            prop="url"
            header-align="center"
            align="center"
            width="150"
            :show-overflow-tooltip="true"
            label="菜单URL"
          >
          </el-table-column>
          <el-table-column
            prop="perms"
            header-align="center"
            align="center"
            width="150"
            :show-overflow-tooltip="true"
            label="授权标识"
          >
          </el-table-column>
          <el-table-column
            fixed="right"
            header-align="center"
            align="center"
            width="180"
            label="操作"
          >
            <template #default="{ row }">
              <el-button v-permission="'sys:menu:update'" @click="handleEdit(row)">编辑</el-button>
              <el-button v-permission="'sys:menu:delete'" @click="handleDelete(row)"
                >删除</el-button
              >
            </template>
          </el-table-column>
        </el-table>
      </template>
    </container-box>
    <el-dialog
      class="common-el-dialog"
      lock-scroll
      top="10vh"
      v-model="menuDialog"
      :title="menuDialogType === 'add' ? '新增' : '编辑'"
      width="600"
      @close="handleClose"
    >
      <el-form
        status-icon
        :model="dataForm"
        :rules="dataRule"
        ref="formRef"
        @keyup.enter.native="dataFormSubmit"
        label-width="80px"
      >
        <el-form-item label="类型" prop="type">
          <el-radio-group v-model="dataForm.type">
            <el-radio
              v-for="type in dataTypeList"
              :label="type.label"
              :key="type.id"
              :value="type.id"
            ></el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item :label="dataTypeList[dataForm.type]['label'] + '名称'" prop="name">
          <el-input
            v-model="dataForm.name"
            :placeholder="dataTypeList[dataForm.type]['label'] + '名称'"
          ></el-input>
        </el-form-item>
        <el-form-item label="上级菜单" prop="parentName">
          <el-popover
            popper-class="form-item-popper"
            ref="menuListPopover"
            placement="bottom-start"
            trigger="click"
          >
            <el-tree
              class="common-el-tree hx-scroll"
              :data="selectMenuTree"
              node-key="menuId"
              ref="menuListTreeRef"
              @node-click="selectTreeNodeClick"
              :default-expand-all="true"
              :highlight-current="true"
              :props="menuListTreeProps"
              :expand-on-click-node="false"
            >
            </el-tree>
            <template #reference>
              <el-input
                v-model="dataForm.parentName"
                readonly
                placeholder="点击选择上级菜单"
                class="menu-list__input"
              ></el-input>
            </template>
          </el-popover>
        </el-form-item>
        <el-form-item v-if="dataForm.type === 1" label="菜单路由" prop="url">
          <el-input v-model="dataForm.url" placeholder="菜单路由"></el-input>
        </el-form-item>
        <el-form-item v-if="dataForm.type === 2" label="授权标识" prop="perms">
          <el-input
            v-model="dataForm.perms"
            placeholder="多个用逗号分隔, 如: user:list,user:create"
          ></el-input>
        </el-form-item>
        <el-form-item v-if="dataForm.type !== 2" label="排序号" prop="orderNum">
          <el-input-number
            v-model="dataForm.orderNum"
            controls-position="right"
            :min="0"
            label="排序号"
          ></el-input-number>
        </el-form-item>
        <el-form-item v-if="dataForm.type !== 2" label="菜单图标" prop="icon">
          <el-popover
            ref="iconListPopover"
            placement="top-start"
            trigger="click"
            popper-class="mod-menu__icon-popover"
          >
            <div class="mod-menu__icon-list hx-scroll">
              <el-button
                v-for="(item, index) in iconList"
                :key="index"
                :title="item.name"
                @click="onSelectIcon(item)"
                :type="item.font_class === dataForm.icon ? 'success' : ''"
              >
                <IconSvg :icon-class="item.font_class"></IconSvg>
              </el-button>
            </div>
            <template #reference>
              <el-input
                v-model="dataForm.icon"
                :readonly="true"
                placeholder="菜单图标名称"
                class="icon-list__input"
              ></el-input>
            </template>
          </el-popover>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="menuDialog = false">取消</el-button>
          <el-button type="primary" @click="dataFormSubmit()">确定</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref, onMounted, getCurrentInstance, nextTick } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import ContainerBox from '@/components/base/ContainerBox.vue'
import { iconList } from '@/utils/iconfontList.js'
import accessApi from '@/api/accessApi.js'
import message from '@/utils/elMessage.js'
import IconSvg from '@/components/base/Icon-svg.vue'

const { proxy } = getCurrentInstance()
onMounted(() => {
  getMenuManageList()
})

const tableData = ref([])
const isLoadingTable = ref(false)
const dataTypeList = [
  { id: 0, label: '目录' },
  { id: 1, label: '菜单' },
  { id: 2, label: '按钮' },
]
const menuListTreeProps = {
  label: 'name',
  children: 'children',
}

//新增、编辑菜单
const menuDialog = ref(false)
const menuDialogType = ref('add')
const formRef = ref(null)
const dataForm = ref({
  id: 0,
  type: 1,
  name: '',
  parentId: 0,
  parentName: '',
  url: '',
  perms: '',
  orderNum: 0,
  icon: '',
  iconList: [],
})
const validateUrl = (rule, value, callback) => {
  if (dataForm.value.type === 1 && !/\S/.test(value)) {
    callback(new Error('菜单URL不能为空'))
  } else {
    callback()
  }
}
const dataRule = ref({
  name: [{ required: true, message: '菜单名称不能为空', trigger: 'blur' }],
  parentName: [{ required: true, message: '上级菜单不能为空', trigger: 'change' }],
  url: [{ validator: validateUrl, trigger: 'blur' }],
})
// 上级菜单下拉树形数据
const menuListTreeRef = ref(null)
const selectMenuTree = ref([])

//获取菜单管理list
function getMenuManageList() {
  isLoadingTable.value = true
  accessApi
    .getMenuManageList({
      t: Date.now(),
    })
    .then((res) => {
      if (Array.isArray(res)) {
        tableData.value = proxy.$utils.arrayToTree(res || [], {
          idKey: 'menuId',
          parentKey: 'parentId',
          childrenKey: 'children',
        })
      } else {
        message.warning(res.msg)
      }
    })
    .finally(() => {
      isLoadingTable.value = false
    })
}

// 编辑
function handleEdit(row) {
  if (row.menuId) {
    openMenuDialog('edit', row.menuId)
  }
}

//删除
function handleDelete(row) {
  if (row.menuId) {
    message.confirm('您是否确定要删除该菜单?', '提示').then(() => {
      accessApi
        .deleteSysMenu(row.menuId, {
          t: Date.now(),
        })
        .then((res) => {
          if (res.code === 0) {
            message.success(res.msg)
            getMenuManageList()
          } else {
            message.warning(res.msg)
          }
        })
        .catch((error) => {
          console.error(error.messages)
        })
    })
  }
}

function getSelectMenu() {
  return new Promise((resolve) => {
    accessApi
      .getSelectMenu({
        t: Date.now(),
      })
      .then((res) => {
        if (res.code === 0) {
          const treeData = proxy.$utils.arrayToTree(res.menuList || [], {
            idKey: 'menuId',
            parentKey: 'parentId',
            childrenKey: 'children',
          })
          resolve(treeData)
        } else {
          message.warning(res.msg)
        }
      })
  })
}

const menuListPopover = ref(null)

function selectTreeNodeClick(data) {
  dataForm.value.parentId = data.menuId
  dataForm.value.parentName = data.name
  nextTick(() => {
    menuListPopover.value.hide()
  })
}

function onSelectIcon(item) {
  dataForm.value.icon = item.font_class
}

//表单提交
function dataFormSubmit() {
  formRef.value.validate((bool) => {
    if (bool) {
      const params = {
        languageType: 'zh',
        menuId: dataForm.value.id || undefined,
        type: dataForm.value.type,
        name: dataForm.value.name,
        parentId: dataForm.value.parentId,
        url: dataForm.value.url,
        perms: dataForm.value.perms,
        orderNum: dataForm.value.orderNum,
        icon: dataForm.value.icon,
      }
      const fetchApi =
        menuDialogType.value === 'add' ? accessApi.saveSysMenu : accessApi.updateSysMenu
      fetchApi(params).then((res) => {
        if (res.code === 0) {
          message.success(res.msg || '操作成功')
          menuDialog.value = false
          getMenuManageList()
        } else {
          message.warning(res.msg)
        }
      })
    }
  })
}

//通用打开新增、编辑弹窗方法
async function openMenuDialog(type, menuId) {
  //获取弹窗中菜单list数据
  selectMenuTree.value = await getSelectMenu()
  //编辑反查
  if (type !== 'add' && menuId) {
    await lookMenuInfo(menuId)
  }
  menuDialogType.value = type
  menuDialog.value = true
  await nextTick(() => {
    menuListTreeSetCurrentNode()
  })
}

//反查当前菜单信息
function lookMenuInfo(menuId) {
  return new Promise((resolve) => {
    accessApi
      .checkSysMenu(menuId, {
        t: Date.now(),
      })
      .then((res) => {
        if (res.code === 0) {
          const menuForm = res.menu || {}
          dataForm.value.id = menuForm.menuId
          dataForm.value.type = menuForm.type
          dataForm.value.name = menuForm.name
          dataForm.value.parentId = menuForm.parentId
          dataForm.value.url = menuForm.url
          dataForm.value.perms = menuForm.perms
          dataForm.value.orderNum = menuForm.orderNum
          dataForm.value.icon = menuForm.icon
          resolve(menuForm)
        } else {
          message.warning(res.msg)
        }
      })
  })
}

function menuListTreeSetCurrentNode() {
  menuListTreeRef.value.setCurrentKey(dataForm.value.parentId)
  dataForm.value.parentName = (menuListTreeRef.value.getCurrentNode() || {})['name']
}

function handleClose() {
  formRef.value.resetFields()
  if (menuListTreeRef.value) {
    //取消当前选择
    menuListTreeRef.value.setCurrentKey(null)
  }
}
</script>

<style scoped lang="scss">
.menu-box {
}
</style>
<style lang="scss">
.mod-menu__icon-popover {
  min-width: 360px !important;

  .mod-menu__icon-list {
    max-height: 180px;
    overflow-y: auto;

    .el-button {
      margin: 8px 0 0 8px;
      padding: 8px;
    }
  }
}
</style>
